﻿using System;
using System.Diagnostics;
using FirstFloor.Documents.Controls;

namespace FirstFloor.Documents.Presentation
{
    /// <summary>
    /// Extends the document view model by loading/unloading the pages that are visible in a book control.
    /// </summary>
    /// <remarks>
    /// This view model ensures there are max six pages loaded at any given time. Six is the total of the two visible pages plus the previous two and the next two pages.
    /// </remarks>
    public class BookViewModel
        : DocumentViewModel
    {
        private PagePosition firstPagePosition = PagePosition.Right;

        /// <summary>
        /// Determines the position of the book's first page.
        /// </summary>
        /// <value>The first page position.</value>
        public PagePosition FirstPagePosition
        {
            get { return this.firstPagePosition; }
            set
            {
                if (this.firstPagePosition != value) {
                    this.firstPagePosition = value;
                    OnPropertyChanged("FirstPagePosition");
                }
            }
        }

        /// <summary>
        /// Called before the current page is changing.
        /// </summary>
        /// <param name="pageIndex">Index of the new page.</param>
        protected override void OnPageChanging(ref int pageIndex)
        {
            if (pageIndex != -1 && pageIndex % 2 == 1) {
                // calculate correct page index given the position of the first page
                if (this.FirstPagePosition == PagePosition.Left) {
                    pageIndex = Math.Max(pageIndex - 1, 0);
                }
                else if (this.FirstPagePosition == PagePosition.Right) {
                    pageIndex = Math.Min(pageIndex + 1, this.PageCount - 1);
                }
            }
        }

        /// <summary>
        /// Called when the current page has changed
        /// </summary>
        /// <param name="oldPage">The old page.</param>
        /// <param name="newPage">The new page.</param>
        protected override void OnPageChanged(PageContextBase oldPage, PageContextBase newPage)
        {
            // load/unload visible pages
            var index = this.PageIndex;

            Debug.WriteLine("New current page: {0}", index);

            var i = 0;
            foreach (var page in this.Pages) {
                // visible page range depends on the position of the first page, calculate it
                var minIndex = this.FirstPagePosition == PagePosition.Left ? index - 2 : index - 3;
                var maxIndex = this.FirstPagePosition == PagePosition.Right ? index + 2 : index + 3;

                var isInuse = (i >= minIndex && i <= maxIndex);

                if (isInuse && !page.IsInUse) {
                    Debug.WriteLine("Loading page {0}", i);
                }
                else if (!isInuse && page.IsInUse) {
                    Debug.WriteLine("Unloading page {0}", i);
                }
                page.IsInUse = isInuse;

                i++;
            }
        }

        /// <summary>
        /// Sets the page navigation command states.
        /// </summary>
        protected override void SetPageNavigationCommandStates()
        {
            this.CanGoToNextPage = this.PageIndex < this.PageCount - 1 && this.PageCount != 0;
            this.CanGoToPreviousPage = this.PageIndex > 1;
        }

        /// <summary>
        /// Navigates to the next page.
        /// </summary>
        public override void GoToNextPage()
        {
            if (CanGoToNextPage) {
                this.PageIndex += 2;
            }
        }

        /// <summary>
        /// Navigates to the previous page.
        /// </summary>
        public override void GoToPreviousPage()
        {
            if (CanGoToPreviousPage) {
                this.PageIndex -= 2;
            }
        }
    }
}
